package cn.lhn.ridersclub.service;

import cn.lhn.ridersclub.controller.FileController;
import cn.lhn.ridersclub.dto.AccountDto;
import cn.lhn.ridersclub.entity.Account;
import cn.lhn.ridersclub.entity.Grade;
import cn.lhn.ridersclub.entity.Login;
import cn.lhn.ridersclub.mapper.AccountMapper;
import cn.lhn.ridersclub.mapper.LoginMapper;
import cn.lhn.ridersclub.util.IdUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.stereotype.Service;

import java.nio.file.Files;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

@Service
public class AccountServiceImpl implements AccountService {

    private final AccountMapper accountMapper;

    private final LoginMapper loginMapper;

    private final CaptchaService captchaService;

    private final GradeService gradeService;

    private final PaperService paperService;

    private final AccountFollowService accountFollowService;

    public AccountServiceImpl(AccountMapper accountMapper, LoginMapper loginMapper, CaptchaService captchaService, GradeService gradeService, PaperService paperService, AccountFollowService accountFollowService) {
        this.accountMapper = accountMapper;
        this.loginMapper = loginMapper;
        this.captchaService = captchaService;
        this.gradeService = gradeService;
        this.paperService = paperService;
        this.accountFollowService = accountFollowService;
    }

    @Override
    public AccountDto registerAccount(String email, String code, String gender, String nickname) {

        //  性别校验
        if (gender == null || !gender.matches("^男$|^女$|^-$")) {
            throw new RuntimeException("性别格式错误");
        }

        //  查询邮箱是否已被注册
        QueryWrapper<Login> lqw = new QueryWrapper<>();
        lqw.eq("email", email);
        Login login = loginMapper.selectOne(lqw);
        if (login != null) {
            throw new RuntimeException("该邮箱已被注册");
        }

        //  验证码是否正确
        captchaService.verifyCaptcha(email, code);

        //  查询用户名是否已被占用
        QueryWrapper<Account> aqw = new QueryWrapper<>();
        aqw.eq("nickname", nickname);
        Account account = accountMapper.selectOne(aqw);
        if (account != null) {
            throw new RuntimeException("用户名已被占用");
        }

        //  生成账号ID
        long id = IdUtil.createId();
        account = new Account(id, nickname, gender, null, null, null, LocalDateTime.now());

        //  添加账号记录
        int i = accountMapper.insert(account);
        if (i != 1) {
            throw new RuntimeException("注册失败");
        }

        //  设置随机头像
        String g = new Random().nextInt(4) + ".png";
        try {
            String from = FileController.FILE_BASE_PATH + "image/header/default/" + g;
            String path = FileController.FILE_BASE_PATH + "image/header/" + id + ".png";
            Files.copy(Paths.get(from), Paths.get(path));
        }
        catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e.getMessage());
        }

        //  注册完成
        return toAccountDto(account);
    }

    @Override
    public AccountDto closeAccount(String email, String code) {
        //  查询邮箱是否存在
        QueryWrapper<Login> wrapper = new QueryWrapper<>();
        wrapper.eq("email", email);
        Login login = loginMapper.selectOne(wrapper);
        if (login == null) {
            throw new RuntimeException("账号不存在");
        }
        Account account = accountMapper.selectById(login.getId());
        if (account == null) {
            throw new RuntimeException("账号不存在");
        }

        //  验证码校验
        captchaService.verifyCaptcha(email, code);

        //  移除账号记录
        int i = accountMapper.deleteById(account.getId());
        if (i != 1) {
            throw new RuntimeException("注销失败");
        }

        //  移除头像
        try {
            String path = FileController.FILE_BASE_PATH + "image/header/" + account.getId() + ".png";
            Files.delete(Paths.get(path));
        }
        catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e.getMessage());
        }

        return toAccountDto(account);
    }

    @Override
    public AccountDto getAccount(Long id) {
        return toAccountDto(accountMapper.selectById(id));
    }

    @Override
    public AccountDto getAccount(String nickname) {
        QueryWrapper<Account> wrapper = new QueryWrapper<>();
        wrapper.eq("nickname", nickname);
        return toAccountDto(accountMapper.selectOne(wrapper));
    }

    @Override
    public List<AccountDto> getAccounts(String nickname) {
        QueryWrapper<Account> qw = new QueryWrapper<>();
        qw.like("nickname", nickname);
        List<Account> accountList = accountMapper.selectList(qw);
        List<AccountDto> list = new ArrayList<>();
        for (Account account : accountList) {
            list.add(toAccountDto(account));
        }
        return list;
    }

    @Override
    public void updateAccount(Account account) {

        QueryWrapper<Account> qw = new QueryWrapper<>();
        qw.eq("nickname", account.getNickname());
        Account one = accountMapper.selectOne(qw);
        if (one != null && !one.getId().equals(account.getId())) {
            throw new RuntimeException("用户名已被占用");
        }

        int i = accountMapper.updateById(account);
        if (i != 1) {
            throw new RuntimeException("更新失败");
        }
    }

    @Override
    public AccountDto toAccountDto(Account account) {

        //  等级
        Grade grade = gradeService.getGrade(account.getId());
        Long maxGradeValue = gradeService.getMaxGradeValue(grade.getGrade());

        //  文章输数量
        Long paperCount = paperService.getPaperCount(account.getId());

        //  关注数和粉丝数
        Long followCount = accountFollowService.getFollowCount(account.getId());
        Long fansCount = accountFollowService.getFansCount(account.getId());

        return AccountDto
                .builder()
                .id(account.getId())
                .nickname(account.getNickname())
                .gender(account.getGender())
                .profile(account.getProfile())
                .birth(account.getBirth())
                .createTime(account.getCreateTime())
                .grade(grade.getGrade())
                .currentGradeValue(grade.getCurrentGradeValue())
                .maxGradeValue(maxGradeValue)
                .paperCount(paperCount)
                .followCount(followCount)
                .fansCount(fansCount)
                .build();
    }

    @Override
    public Account toAccount(AccountDto dto) {
        return Account
                .builder()
                .id(dto.getId())
                .nickname(dto.getNickname())
                .gender(dto.getGender())
                .birth(dto.getBirth())
                .city("")
                .profile(dto.getProfile())
                .createTime(dto.getCreateTime())
                .build();
    }
}
